package com.tuyrt.windy.logic

import androidx.lifecycle.liveData
import com.tuyrt.windy.logic.dao.PlaceDao
import com.tuyrt.windy.logic.model.Place
import com.tuyrt.windy.logic.model.Weather
import com.tuyrt.windy.logic.network.WindyWeatherNetwork
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlin.coroutines.CoroutineContext


/**
 * Created by tuyrt7 on 2021/4/14.
 */
object Repository {

    fun savePlace(place: Place) = PlaceDao.savePlace(place)
    fun getPlace() = PlaceDao.getPlace()
    fun isPlaceSaved() = PlaceDao.isPlaceSaved()

    fun searchPlaces(query: String) = fire(Dispatchers.IO) {
        val searchPlaces = WindyWeatherNetwork.searchPlaces(query)
        if ("ok" == searchPlaces.status) {
            Result.success(searchPlaces.places)
        } else {
            Result.failure(RuntimeException("response status is ${searchPlaces.status}"))
        }
    }

    fun refreshWeather(lat: String, lng: String) = fire(Dispatchers.IO) {
        coroutineScope {
            val deferredDaily = async {
                WindyWeatherNetwork.getDaily(lat, lng)
            }
            val deferredRealtime = async {
                WindyWeatherNetwork.getRealtime(lat, lng)
            }

            val dailyResponse = deferredDaily.await()
            val realTimeResponse = deferredRealtime.await()

            if (dailyResponse.status == "ok" && realTimeResponse.status == "ok") {
                val weather =
                    Weather(realTimeResponse.result.realtime, dailyResponse.result.daily)
                Result.success(weather)
            } else {
                Result.failure(
                    RuntimeException(
                        "realTime response status is ${realTimeResponse.status} " +
                                "daily response status is ${dailyResponse.status} "
                    )
                )
            }
        }
    }

    private fun <T> fire(context: CoroutineContext, block: suspend () -> Result<T>) =
        liveData(context) {
            val result = try {
                block()
            } catch (e: Exception) {
                Result.failure(e)
            }
            emit(result)
        }

}